Open
Conversation
compulim
commented
Mar 25, 2026
__tests__/html2/transcript/legacyActivityMiddleware.reactionButtons.html
Show resolved
Hide resolved
compulim
commented
Mar 25, 2026
compulim
commented
Mar 25, 2026
avatarMiddleware to polymiddlewareavatarMiddleware to polymiddleware
Contributor
There was a problem hiding this comment.
Pull request overview
This PR continues the migration from legacy avatarMiddleware toward the newer polymiddleware system by introducing avatar polymiddleware support (including legacy bridging), updating the default UI middleware wiring to prioritize legacy middleware ahead of polymiddleware, and reducing unnecessary re-renders via iterable memoization utilities.
Changes:
- Added avatar polymiddleware support across
api,api-middleware,component, andbundle, including legacy-to-polymiddleware bridging and new avatar middleware tests/docs. - Introduced
iterateEquals+useMemoIterableto memoize iterable results and reduce wasted re-renders (e.g.,<AddFullBundle>, middleware array patching, polymiddleware composer extraction). - Moved/centralized
singleToArray+OneOrManyinto@msinternal/botframework-webchat-base/utilsand updated references.
Reviewed changes
Copilot reviewed 73 out of 92 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/test/page-object/src/globals/testHelpers/createRunHookActivityMiddleware.js | Test harness: track/guard repeated hook execution during re-renders. |
| packages/test/page-object/src/globals/testHelpers/createDirectLineWithTranscript.js | Test helper: add optional activity patching hook for transcripts. |
| packages/test/page-object/src/globals/testHelpers/activityGrouping/ActivityGroupingSurface.js | Test helper: switch activity mutation from middleware to transcript patching. |
| packages/react-hooks/src/useMemoIterable.ts | New hook to memoize iterables via structural equality. |
| packages/react-hooks/src/useDebugDeps.ts | New debug deps hook moved into shared react-hooks package. |
| packages/react-hooks/src/index.ts | Export new hooks from react-hooks package. |
| packages/react-hooks/package.json | Add local/dev dependency wiring for base utils. |
| packages/core/src/utils/singleToArray.ts | Remove core-local singleToArray (moved to base utils). |
| packages/core/src/types/OneOrMany.ts | Remove core-local OneOrMany (moved to base utils). |
| packages/core/src/index.ts | Re-export deprecated singleToArray/OneOrMany from base utils; tidy imports. |
| packages/core-debug-api/src/RestrictedDebugAPI.ts | ESLint disable cleanup for empty breakpoint function. |
| packages/component/src/index.ts | Point createCoreActivityMiddleware export to updated activity polymiddleware module. |
| packages/component/src/boot/internal.ts | Export internal avatar-styleOptions symbol type for portability. |
| packages/component/src/Utils/singleToArray.ts | Remove component-local singleToArray (moved to base utils). |
| packages/component/src/Transcript/hooks/useRenderActivityProps.ts | Use avatar polymiddleware render callback instead of legacy avatar renderer hook. |
| packages/component/src/Middleware/Avatar/createDefaultAvatarPolymiddleware.tsx | New default avatar polymiddleware factory driven by style options. |
| packages/component/src/Middleware/Avatar/DefaultAvatar.tsx | Convert default avatar from legacy middleware factory to memoized component export. |
| packages/component/src/Middleware/Activity/defaultActivityPolymiddleware.tsx | Bridge default legacy activity middleware into a polymiddleware (and keep compat export). |
| packages/component/src/Composer.tsx | Memoize middleware arrays; wire default activity/avatar via polymiddleware (lower priority than legacy). |
| packages/component/src/BasicTranscript.tsx | Memoize internal transcript component to reduce wasted renders. |
| packages/component/src/Activity/Avatar.tsx | Update imports to new DefaultAvatar component export. |
| packages/bundle/src/useComposerProps.ts | Allow optional attachment middleware arrays; avoid spreading undefined. |
| packages/bundle/src/boot/actual/middleware.ts | Export avatar polymiddleware APIs from bundle middleware entry. |
| packages/bundle/src/AddFullBundle.tsx | Use useMemoIterable to avoid rerenders when attachment middleware values are equivalent. |
| packages/bundle/package.json | Add dependency on internal react-hooks package. |
| packages/base/src/utils/singleToArray.ts | New shared deprecated singleToArray in base utils. |
| packages/base/src/utils/iterateEquals.ts | New iterable structural-equality helper. |
| packages/base/src/utils/iterateEquals.spec.ts | Unit tests for iterateEquals. |
| packages/base/src/utils/index.ts | Export new base utils (iterateEquals, OneOrMany, singleToArray). |
| packages/base/src/utils/OneOrMany.ts | New shared deprecated OneOrMany type in base utils. |
| packages/api/src/types/AvatarMiddleware.ts | Extend legacy avatar middleware request typing to preserve original polymiddleware request. |
| packages/api/src/providers/GroupActivities/GroupActivitiesComposer.tsx | Allow groupActivitiesMiddleware to be optional. |
| packages/api/src/middleware/useBuildRenderAvatarCallback.ts | API-layer patch to add styleOptions into internal avatar request (bridging constraint). |
| packages/api/src/middleware/AvatarPolymiddlewareProxy.tsx | API-layer proxy wrapper that injects style options into raw proxy. |
| packages/api/src/legacy/createAvatarPolymiddlewareFromLegacy.tsx | New legacy avatar middleware bridge into avatar polymiddleware. |
| packages/api/src/legacy/createActivityPolymiddlewareFromLegacy.tsx | Add debug metadata to activity polymiddleware bridged from legacy middleware. |
| packages/api/src/legacy/LegacyActivityBridge.tsx | Add displayName for legacy activity bridge component. |
| packages/api/src/hooks/useCreateAvatarRenderer.ts | Deprecate legacy avatar renderer hook; implement via avatar polymiddleware callback. |
| packages/api/src/hooks/internal/useDebugDeps.js | Remove old API-local debug deps hook (moved to react-hooks package). |
| packages/api/src/hooks/internal/WebChatAPIContext.ts | Remove legacy avatarRenderer from API context typing. |
| packages/api/src/hooks/Composer.tsx | Prioritize legacy middleware before polymiddleware; bridge legacy avatar middleware into polymiddleware. |
| packages/api/src/boot/middleware.ts | Export avatar polymiddleware APIs and legacy bridge factory from API boot middleware entry. |
| packages/api/src/boot/internal.ts | Export internal avatar styleOptions symbol from api-middleware. |
| packages/api-middleware/src/private/templatePolymiddleware.tsx | Attach debug metadata (name/enhancer) to templated polymiddleware factories. |
| packages/api-middleware/src/legacy/avatarMiddleware.ts | Introduce legacy avatar middleware typings/symbol for bridging. |
| packages/api-middleware/src/legacy.ts | Export legacy avatar middleware types from api-middleware. |
| packages/api-middleware/src/index.ts | Export avatar polymiddleware APIs and legacy avatar symbol from api-middleware. |
| packages/api-middleware/src/avatarPolymiddleware.tsx | Add avatar polymiddleware implementation (provider/proxy/extract/build-render). |
| packages/api-middleware/src/PolymiddlewareComposer.tsx | Add avatar polymiddleware provider to composer; switch memoization to useMemoIterable. |
| packages/api-middleware/package.json | Adjust watch inputs for notify-build script. |
| package-lock.json | Lockfile updates for new internal package dependency wiring. |
| docs/MIDDLEWARE.md | Document avatar polymiddleware support and update priority rules. |
| tests/html2/transcript/legacyActivityMiddleware.reactionButtons.html | Refactor legacy activity middleware test for clearer wrapping logic. |
| tests/html2/timestamp/attachmentSendTimeout.html | Guard against repeated execution via updated RunHook helper. |
| tests/html2/scrollToEndButton/scrollToEndButton.persistWhileCallingUseScrollTo.html | Modernize test harness usage; wait-for assertion stabilization. |
| tests/html2/middleware/avatar/useBuildRenderAvatarCallback.html.snap-1.png | New snapshot for avatar build-render-callback test. |
| tests/html2/middleware/avatar/useBuildRenderAvatarCallback.html | New test verifying useBuildRenderAvatarCallback behavior with legacy + polymiddleware. |
| tests/html2/middleware/avatar/renderProxy.html.snap-1.png | New snapshot for avatar proxy rendering test. |
| tests/html2/middleware/avatar/renderProxy.html | New test verifying <AvatarPolymiddlewareProxy> behavior with legacy + polymiddleware. |
| tests/html2/middleware/avatar/polymiddleware/delete.html | New test: polymiddleware deletes avatar for specific activities. |
| tests/html2/middleware/avatar/polymiddleware/defaultAvatar.styleOptions.html.snap-2.png | Snapshot for default avatar behavior after styleOptions change. |
| tests/html2/middleware/avatar/polymiddleware/defaultAvatar.styleOptions.html.snap-1.png | Snapshot for default avatar behavior baseline. |
| tests/html2/middleware/avatar/polymiddleware/defaultAvatar.styleOptions.html | New test: default avatar responds to styleOptions changes. |
| tests/html2/middleware/avatar/polymiddleware/decorate.html | New test: polymiddleware decorates avatar output. |
| tests/html2/middleware/avatar/polymiddleware/changing.html | New test: toggling polymiddleware on/off at runtime. |
| tests/html2/middleware/avatar/polymiddleware/addOrReplace.html | New test: polymiddleware adds/replaces avatar output for certain roles. |
| tests/html2/middleware/avatar/legacyAvatarMiddleware/styleOptions.html | New test: legacy avatar middleware receives styleOptions and reacts to changes. |
| tests/html2/middleware/avatar/legacyAvatarMiddleware/delete.html | New test: legacy avatar middleware deletes avatar for certain roles. |
| tests/html2/middleware/avatar/legacyAvatarMiddleware/decorate.html | New test: legacy avatar middleware decorates avatar output. |
| tests/html2/middleware/avatar/legacyAvatarMiddleware/changing.html | New test: toggling legacy avatar middleware on/off at runtime. |
| tests/html2/middleware/avatar/legacyAvatarMiddleware/addOrReplace.html | New test: legacy avatar middleware adds/replaces avatar output. |
| tests/html2/middleware/avatar/backwardCompatibility.html | New test: legacy avatar middleware priority over polymiddleware for compatibility. |
| tests/html2/activityGrouping/activityGrouping.legacyActivityMiddleware.skip.html | Mark failing legacy activity middleware test with explanatory skip rationale. |
| CHANGELOG.md | Changelog entries for avatarMiddleware deprecation + polymiddleware support + rerender fix. |
| AGENTS.md | Update contributor guidance (immutability, validation, tooling/testing conventions). |
| .github/workflows/pull-request-validation.yml | Update CI runner matrix (macOS label change). |
| .github/agents/polymiddleware-promoter.agent.md | Add agent guidance for upgrading middleware to polymiddleware. |
| .eslintrc.yml | Broaden unused-args ignore pattern for underscore-prefixed args. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
packages/component/src/Middleware/Avatar/createDefaultAvatarPolymiddleware.tsx
Show resolved
Hide resolved
packages/test/page-object/src/globals/testHelpers/createDirectLineWithTranscript.js
Outdated
Show resolved
Hide resolved
OEvgeny
reviewed
Mar 25, 2026
OEvgeny
reviewed
Mar 25, 2026
OEvgeny
reviewed
Mar 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changelog Entry
avatarMiddlewareis being deprecated in favor ofpolymiddleware. It will be removed on or after 2028-03-18, related to PR #5779Added
polymiddleware, a new universal middleware for every UIs, by @compulim in PR #5515 and #5566Removed
avatarMiddlewareis being deprecated in favor ofpolymiddleware. It will be removed on or after 2028-03-18, related to PR #5779Fixed
<AddFullBundle>should not re-render whenattachment[ForScreenReader]Middlewareis updated without noticeable different (iterateEquals), by @compulim, in PR #5779Description
Upgraded avatar middleware to
avatarPolymiddleware.Unified and memorized the
singleToArray(middleware ?? [])pattern.Also fixed wasted rendering in
<AddFullBundle>.Also fixed test harness legacy
<RunHook>that is being rendered multiple times:<RunHook>is not memorized<RunHook>subscribes to context which is changed, then the render loop is re-executedDesign
Why render legacy middleware before polymiddleware?
componentpackage, and passed viapolymiddlewarepropsapipackageWe have a few way out, either one of the followings:
lowPriorityPolymiddlewareprops for default polymiddleware, so we can put them after legacyapiandcomponentpackagecomponentwill upgrade legacy to polymiddleware and prioritize properlyapipackageThe simplest and logical move is
#3: render legacy middleware before polymiddleware.Specific Changes
baseandreact-hookspackagesuseMemoIterableto help memorizing iterable resultsRunHookActivitycould re-render and running hooks multiple timesuseXXXhooks will be invalidated and causing the component to be re-renderedCHANGELOG.mdReview Checklist
Accessibility reviewed (tab order, content readability, alt text, color contrast)Browser and platform compatibilities reviewedCSS styles reviewed (minimal rules, noz-index)Internationalization reviewed (strings, unit formatting)package.jsonandpackage-lock.jsonreviewedSecurity reviewed (no data URIs, check for nonce leak)